/*
 * Created on Feb 4, 2005
 * Created by dfhuynh
 */
package edu.mit.simile.longwell;

import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.log4j.Logger;

import edu.mit.simile.longwell.corpus.Corpus;
import edu.mit.simile.longwell.schema.impl.SchemaRegistry;

/**
 * @author dfhuynh
 */
public class LongwellServer {
	final static private Logger s_logger =
		Logger.getLogger(LongwellServer.class);

	static private LongwellServer s_singleton = null;

	protected Profile	m_defaultProfile;
	protected Map		m_profiles = new HashMap();

	final static public LongwellServer getServer() {
		return s_singleton;
	}

	/**
	 * @param defaultCorpus
	 * @param defaultCorpusSystemDir
	 * @param commonSystemDir
	 * @throws Exception
	 */
	public LongwellServer(
		Corpus	defaultCorpus,
		File	defaultCorpusSystemDir,
		File	commonSystemDir
	) throws Exception {
		s_logger.info("Creating Longwell server:\n" +
			"\tdefault corpus system dir: " + defaultCorpusSystemDir.getCanonicalPath() + "\n" +
			"\tcommon system dir:         " + commonSystemDir.getCanonicalPath());

		try {
			if (s_singleton == null) {
				s_singleton = this;
				SchemaRegistry.startup(new File(commonSystemDir, "schema-registry"));
			}

			m_defaultProfile = createDefaultProfile(
				defaultCorpus, defaultCorpusSystemDir);
		} catch (Exception e) {
			s_logger.error("Failed to construct Longwell server", e);
			throw e;
		}
	}

	/**
	 * Dispose the server and free up resources.
	 */
	synchronized public void dispose() {
		Iterator i = m_profiles.values().iterator();
		while (i.hasNext()) {
			((Profile) i.next()).dispose();
		}
		m_profiles.clear();

		if (m_defaultProfile != null) {
			m_defaultProfile.dispose();
			m_defaultProfile = null;
		}

		if (s_singleton == this) {
			SchemaRegistry.shutdown();
			s_singleton = null;
		}

		//Cache.printSummary();
	}

	/**
	 * Answer the default local profile.
	 *
	 * @return
	 */
	synchronized public Profile getDefaultProfile() {
		return m_defaultProfile;
	}

	/**
	 * Answer the profile with the given name
	 *
	 * @param name
	 * @return
	 */
	synchronized public Profile getProfile(String id) {
		if (m_defaultProfile.getID().equals(id)) {
			return getDefaultProfile();
		} else {
			return (Profile) m_profiles.get(id);
		}
	}

	protected Profile createDefaultProfile(
		Corpus	corpus,
		File	structuredModelsDir
	) {
		return new LocalProfile(
			"default",
			corpus,
			structuredModelsDir
		);
	}

	protected void addProfile(String id, Profile profile) {
		m_profiles.put(id, profile);
	}

	protected void removeProfile(String id) {
		m_profiles.remove(id);
	}
}
